<template>
  <div class="person">
    <h2>姓名：{{ person.name }}</h2>
    <h3>年龄：{{ person.age }}</h3>
    <h4>汽车：{{ person.car.c1 }}、 {{ person.car.c2 }}</h4>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changeC1e">修改第一台汽车</button>
    <button @click="changeC2">修改第二台汽车</button>
    <button @click="changeCar">修改整个车</button>
  </div>
  
</template>



<script lang="ts" setup name="Person">
import { reactive, watch } from 'vue'

let person = reactive({
  name: 'John',
  age: 25,
  car: {
    c1: 'Toyota',
    c2: 'Honda'
  }
})

function changeName() {
  person.name += "~"
}
function changeAge() {
  person.age += 1
}
function changeC1e() {
  person.car.c1 += "奥迪"
}
function changeC2() {
  person.car.c2 += "大众"
}
function changeCar() {
  // 整个能改，但里面的属性可以改
  person.car = {
    c1: '雅迪',
    c2: '艾玛'
  }
}

// watch 监听: 函数返回一个值（getter函数）、ref/reactive定义的数据、前面情况组成的数组
// getter函数,能返回一个值的函数
// 情况四：监视响应式对象中的某个属性,且该属性是基本类型的，写成函数式
/**
 * ref或reactive定义的【对象类型】数据中的某个属性，注意如下：
 * 1、若该属性不是【对象类型】，需要写成函数形式。
 * 2、若该属性依然是【对象类型】，可直接编，也可写成函数，不过建议写成函数。
 * 结论：监视的要是对象里的属性，那么最好写函数式，注意点：若是对象监视的是地址值，需要关注对象内部，需要手动开启深度监视
 */
watch(()=>{
  return person.name
}, (newVal, oldVal) => {
  console.log('person.name changed', newVal, oldVal)
})
// ()=>person.car 写成函数，监视整个car对象；persson.car 监视car对象中的属性
// 这种情况的写法，deep: true 不管用
// watch(person.car, (newVal, oldVal) => {
//  console.log('person.car changed', newVal, oldVal)
// }
// 情况四：监视响应式对象中的某个属性,且该属性是对象类型的，可以直接写，也可写成函数式，更推荐函数式
watch(()=>person.car, (newVal, oldVal) => {
  console.log('person.car changed', newVal, oldVal)
}, {deep: true})


</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px
}

button {
  margin: 0 5px;
}
li {
  font-size: 20px;
}
</style>